Spring ContextLoaderListener 启动流程解析二
- AbstractApplicationContext.obtainFreshBeanFactory
- AbstractRefreshableApplicationContext.refreshBeanFactory
- XmlWebApplicationContext.loadBeanDefinitions
- DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions
- DefaultBeanDefinitionDocumentReader.parseBeanDefinitions
- DefaultBeanDefinitionDocumentReader.parseDefaultElement
- DefaultListableBeanFactory.registerBeanDefinition
本篇博客主要讲的 spring 如何初始化其上下文的源码简单解读。
上次我们讲到了 AbstractApplicationContext.refresh() 这个方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
//容器刷新前准备工作
this.prepareRefresh();
//启动 obtainFreshBeanFactory 里的 refreshBeanFactory() 方法
//主要是把旧的 beanFactory 关闭,重新创建一个 beanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
...
接下来讲解 BeanFactory 是如何创建的。可以看到 beanFactory 是通过 obtainFreshBeanFactory() 这个方法创建的。
AbstractApplicationContext.obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//把旧的 beanFactory 关闭,重新创建一个 beanFactory
this.refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractRefreshableApplicationContext.refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
//删除旧的 beanFactory
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
//用户自定义 beanFactory,不做赘述
this.customizeBeanFactory(beanFactory);
//加载用户的 bean 配置文件
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
XmlWebApplicationContext.loadBeanDefinitions
loadBeanDefinitions 的主要工作就是获取配置,解析配置,得到 xml Document 对象,然后继续进行下面的解析:
DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute("profile");
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createHelper(this.readerContext, root, parent);
this.preProcessXml(root);
//主要看这个方法
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);
this.delegate = parent;
}
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions
parseBeanDefinitions 判断当前解析元素是否属于默认的命名空间,如果是的话,就调用 parseDefaultElement() 方法,否则调用 delegate.parseCustomElement() 方法。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if (delegate.isDefaultNamespace(ele)) {
//当前解析元素属于默认的命名空间,解析 spring 默认的标签,如 <bean/> 这些
this.parseDefaultElement(ele, delegate);
} else {
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
DefaultBeanDefinitionDocumentReader.parseDefaultElement
parseDefaultElement 根据不同的标签元素,调用不同的解析注册方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
一步步跟进,除了 processAliasRegistration 其余方法最终都是 bean 的注册: DefaultListableBeanFactory.registerBeanDefinition
DefaultListableBeanFactory.registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var7) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var7);
}
}
synchronized(this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else {
//添加到 list
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
//把 BeanDefinition 放到 map 中,到此注册就完成了。
//在后面实例化的时候,就是把 beanDefinitionMap 中的 BeanDefinition 取出来,逐一实例化
this.beanDefinitionMap.put(beanName, beanDefinition);
}
this.resetBeanDefinition(beanName);
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 rockeycui@163.com
文章标题:Spring ContextLoaderListener 启动流程解析二
文章字数:773
本文作者:崔石磊(RockeyCui)
发布时间:2018-09-30, 19:00:00
原始链接:https://cuishilei.com/Spring ContextLoaderListener 启动流程解析二.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。